﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Soundelle.Oscillator
{
    public class GeneratorSquare : BaseDevice
    {
        public GeneratorSquare()
        {
        }

        private ParameterType[] _AvailableParameters = { 
            ParameterType.Parameter_DC_Offset,
            ParameterType.Parameter_Amplitude,
            ParameterType.Parameter_Frequency,
            ParameterType.Parameter_Phase,
            ParameterType.Parameter_Duty,
            ParameterType.Parameter_IsZeroPeak
        };
        override public ParameterType[] AvailableParameters
        {
            get
            { return _AvailableParameters; }
        }

        private DeviceFunctionType[] _AvailableFunctions = new DeviceFunctionType[] {
             DeviceFunctionType.Function_GeneratorSquare
        };
        override public DeviceFunctionType[] AvailableFunctions
        {
            get
            { return _AvailableFunctions; }
        }
 
        override protected void InitRmsRatio()
        {
            if (Parameter_IsZeroPeak)
                RmsRatio = Parameter_Duty;
            else
                RmsRatio = 1.0;
        }

        override public double SignalOut()
        {
            if (!Enabled)
                return 0.0;

            double signalOut = 0.0;
            double signalIn = 0.0;

            double DcOffset =Parameter_DC_Offset;
            double amplitude = Parameter_Amplitude;
            double frequency = 0.0;
            double phase = Parameter_Phase;

            double duty = Parameter_Duty;

            DoModulationByChildDevices(ref signalOut, ref signalIn, ref amplitude, ref frequency, ref phase, ref duty);
            frequency = Parameter_Frequency;

            //----

            double sig = 0.0;

            double sigPhaseRatio = frequency * TimePosition / SamplingRate + phase / (2.0 * Math.PI);
            sigPhaseRatio %=  1.0;

            while (sigPhaseRatio < 0.0)
            {
                sigPhaseRatio += 1.0;
            }
            while (sigPhaseRatio > 1.0)
            {
                sigPhaseRatio -= 1.0;
            }

            if (sigPhaseRatio < duty)
            {
                sig = amplitude;
            }
            else
            {
                if (Parameter_IsZeroPeak)
                    sig = 0.0;
                else
                    sig = -amplitude;
            }

            ++TimePosition;
            double SignalOut = sig + amplitude * signalIn + signalOut + DcOffset;
            SetPreviousSignalOut(SignalOut);
            return SignalOut;
        }
    }
}
